package eerbaar.v2.effects;

import java.awt.Color;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;

import eerbaar.game.IGame;
import eerbaar.message.lib.DisplayMessageMsg;
import eerbaar.message.lib.DisplayRisingTextMsg;
import eerbaar.message.lib.TeachingStartedMsg;
import eerbaar.message.lib.TeachingStoppedMsg;
import eerbaar.shared.message.IMessageReader;
import eerbaar.shared.message.Message;
import eerbaar.shared.message.MsgHelper;
import eerbaar.v2.app.GameHelper;
import eerbaar.v2.app.view.Square;
import eerbaar.v2.app.view.Squares;
import eerbaar.v2.app.view.View;
import eerbaar.v2.effects.internal.EffectsFactory;

public class EffectGenerator {

    private final EffectsView view;
    private Effect ringsEffect;
    private int risingTextCount = 0;
    private int popupTextCount = 0;
    private int followingRingsCount = 0;
    private final List<DisplayRisingTextMsg> risingTextList = new ArrayList<DisplayRisingTextMsg>();

    private final IMessageReader risingTextReader = new IMessageReader() {
        @Override
        public boolean read(Message msg) {
            return risingText(msg);
        }
    };

    private final IMessageReader teachingStartedReader = new IMessageReader() {
        @Override
        public boolean read(Message msg) {
            return teachingStarted(msg);
        }
    };

    private final IMessageReader teachingStoppedReader = new IMessageReader() {
        @Override
        public boolean read(Message msg) {
            return teachingStopped(msg);
        }
    };

    private final IMessageReader popupMessageReader = new IMessageReader() {
        @Override
        public boolean read(Message msg) {
            return popupMessage(msg);
        }
    };

    public EffectGenerator(EffectsView view) {
        this.view = view;
    }

    public void check() {

        List<DisplayRisingTextMsg> list = new ArrayList<DisplayRisingTextMsg>();
        for (DisplayRisingTextMsg m : this.risingTextList) {
            list.add(m);
        }

        for (DisplayRisingTextMsg m : list) {
            this.risingText(m);
        }
    }

    private Square findSquare(int x, int y) {

        Square result = null;

        Squares squares = View.getInstance().getSquares();
        Square[] array = squares.getSquares();
        for (Square square : array) {
            if (square.getX() == x && square.getY() == y) {
                result = square;
                break;
            }
        }

        return result;
    }

    private void floatText(IGame game, String text, int inX, int inY,
            eerbaar.commons.Color color) {

        Square square = findSquare(inX, inY);
        Rectangle r = square.getRectangle();
        int y = r.y;
        int x = r.x;
        int height = r.height;
        int width = r.width;
        int top = y + (height / 2);
        int left = x + (width / 2);
        Color c = color.getColor();

        Effect effect = EffectsFactory.createRisingText(text, left, top, c);
        this.view.addEffect(effect);
    }

    private boolean popupMessage(Message msg) {

        IGame game = GameHelper.getGame();
        if (game == null) {
            return false;
        }

        if (!(msg instanceof DisplayMessageMsg)) {
            return false;
        }

        DisplayMessageMsg textMsg = (DisplayMessageMsg) msg;

        popupText(game, textMsg.getMessage());

        return false;
    }

    private void popupText(IGame game, String text) {
        Effect effect = EffectsFactory.createPopupText(text);
        this.view.addEffect(effect);
    }

    private boolean risingText(Message msg) {

        IGame game = GameHelper.getGame();
        if (game == null) {
            return false;
        }

        if (!(msg instanceof DisplayRisingTextMsg)) {
            return false;
        }

        DisplayRisingTextMsg m = (DisplayRisingTextMsg) msg;
        floatText(game, m.getText(), m.getX(), m.getY(), m.getColor());

        return false;
    }

    public void start() {

        if (this.risingTextCount == 0) {
            MsgHelper.registerReader(DisplayRisingTextMsg.class,
                    this.risingTextReader);
            this.risingTextCount++;
        }

        if (this.popupTextCount == 0) {
            MsgHelper.registerReader(DisplayMessageMsg.class,
                    this.popupMessageReader);
            this.popupTextCount++;
        }

        if (this.followingRingsCount == 0) {
            MsgHelper.registerReader(TeachingStartedMsg.class,
                    this.teachingStartedReader);
            MsgHelper.registerReader(TeachingStoppedMsg.class,
                    this.teachingStoppedReader);
            this.followingRingsCount++;
        }

    }

    public void stop() {

        if (this.risingTextCount > 0) {
            MsgHelper.unregisterReader(DisplayRisingTextMsg.class,
                    this.risingTextReader);
            this.risingTextCount--;
        }

        if (this.popupTextCount > 0) {
            MsgHelper.unregisterReader(DisplayMessageMsg.class,
                    this.popupMessageReader);
            this.popupTextCount--;
        }

        if (this.followingRingsCount > 0) {
            MsgHelper.unregisterReader(TeachingStartedMsg.class,
                    this.teachingStartedReader);
            MsgHelper.unregisterReader(TeachingStoppedMsg.class,
                    this.teachingStoppedReader);
            this.followingRingsCount--;
        }

    }

    private boolean teachingStarted(Message msg) {

        if (!(msg instanceof TeachingStartedMsg)) {
            return false;
        }

        // ringsThatFollow();

        return false;
    }

    private boolean teachingStopped(Message msg) {

        if (this.ringsEffect == null) {
            return false;
        }

        this.view.removeEffect(this.ringsEffect);
        this.ringsEffect.setExpired(true);
        this.ringsEffect = null;

        return false;
    }
}
